package com.itany.manager.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itany.manager.entity.Company;
import com.itany.manager.entity.User;
import com.itany.manager.exception.CompanyNotExistException;
import com.itany.manager.exception.UserExistException;
import com.itany.manager.mapper.UserMapper;
import com.itany.manager.service.CompanyService;
import com.itany.manager.service.UserService;
import com.itany.manager.util.ParameterUtil;
import com.itany.manager.vo.UserVO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    private final CompanyService companyService;

    /**
     * 保存用户
     *
     * @param user 用户
     * @return 是否保存成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveUser(User user) {
        if (isNameExists(user.getName())) {
            throw new UserExistException("用户名已存在");
        }

        if (user.getCompanyId() != null && !companyService.existsById(user.getCompanyId())) {
            throw new CompanyNotExistException("指定的公司不存在");
        }

        return save(user);
    }

    /**
     * 检查用户名是否已存在
     */
    private boolean isNameExists(String name) {
        return lambdaQuery()
                .eq(User::getName, name)
                .exists();
    }

    /**
     * 分页查询用户
     *
     * @param pageNo   页码
     * @param pageSize 每页大小
     * @param user     查询条件
     * @return 分页结果
     */
    public Page<UserVO> getUsersByPage(Long pageNo, Long pageSize, User user) {
        // 构建查询条件
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        if (user != null) {
            wrapper.like(!ParameterUtil.isBlank(user.getName()),
                            User::getName, ParameterUtil.escapeString(user.getName()))
                    .eq(!ParameterUtil.isBlank(user.getGender()),
                            User::getGender, user.getGender());
        }
        // 查询总数
        long total = count(wrapper);
        long maxPage = (total + pageSize - 1) / pageSize;
        if (pageNo > maxPage) {
            pageNo = maxPage;
        }
        // 分页查询
        Page<User> userPage = page(new Page<>(pageNo, pageSize), wrapper);
        if (userPage.getRecords().isEmpty()) {
            return new Page<UserVO>(pageNo, pageSize).setTotal(0);
        }
        // 获取公司名称
        Map<Integer, Company> companyMap = getCompany(userPage.getRecords());
        return convertToVoPage(userPage, companyMap);
    }

    /**
     * 获取指定用户列表对应的公司映射表
     *
     * @param users 用户列表
     * @return 公司名称映射表
     */
    private Map<Integer, Company> getCompany(List<User> users) {
        Set<Integer> companyIds = users.stream()
                .map(User::getCompanyId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());

        if (companyIds.isEmpty()) {
            return Collections.emptyMap();
        }

        return companyService.listByIds(companyIds)
                .stream()
                .collect(Collectors.toMap(
                        Company::getId,
                        company -> company,
                        (oldValue, newValue) -> oldValue // 防止数据库出现问题，一个公司ID对应多个公司
                ));
    }

    /**
     * 将用户列表转换为VO分页结果
     *
     * @param sourcePage 用户分页结果
     * @param companyMap 公司映射表
     * @return VO分页结果
     */
    private Page<UserVO> convertToVoPage(Page<User> sourcePage,
                                         Map<Integer, Company> companyMap) {
        List<UserVO> voList = sourcePage.getRecords().stream()
                .map(user -> {
                    Company company = companyMap.get(user.getCompanyId());
                    return UserVO.builder()//
                            .id(user.getId())
                            .name(user.getName())
                            .gender(user.getGender())
                            .companyName(company != null ? company.getCompanyName() : null)
                            .build();
                })
                .collect(Collectors.toList());

        Page<UserVO> resultPage = new Page<>(
                sourcePage.getCurrent(),
                sourcePage.getSize(),
                sourcePage.getTotal()
        );
        resultPage.setRecords(voList);
        return resultPage;
    }
}